The HEAP DEBUGGER V2.0 for BORLAND PASCAL V7.0 (DOS, DOS/DPMI, WINDOWS) Copyright 1995 by AIT GmbH Alte Gasse 12 - 86152 Augsburg Germany Tel. +49 (821) 514868 Fax: +49 (821) 514831 FIDO-Net: Karsten Strobel @ 2:2480/300.7 Internet: kstrobel@gewi.muc.nacamar.de CONTENTS INTRUDUCTION Why Heap Debugging ? ................................................ 3 What the Heap Debugger CAN do........................................ 3 What the Heap Debugger CANNOT do .................................... 3 The usage of Dynamic Memory ......................................... 3 Versions and Targetplatforms ........................................ 4 List of the Files ................................................... 5 Shareware Concept ................................................... 5 Licence Conditions .................................................. 5 Usertips and Warranty Limitation .................................... 6 USING THE HEAP DEBUGGER Linking the Heap Debugger ........................................... 6 Compiler- and Linkeradjustments ..................................... 6 When the Initialization fails ....................................... 7 The Heap Debugger Report ............................................ 7 Special Messages in the Heap Debugger Report ........................ 9 Interpretation of the Report ......................................... 9 Hunting for Bugs .................................................... 10 Working with the External Debugger .................................. 11 Compilerswitches in USEHDEB ......................................... 11 HEAP DEBUGGING IN DETAIL Overlays ............................................................ 12 DLLs ................................................................ 12 Program instances (Windows) ......................................... 13 Interrupts .......................................................... 13 Stability and Performance ........................................... 13 Intervention possibilities for the Programmer ....................... 14 KNOWN LIMITATIONS AND PROBLEMS Mark/Release ........................................................ 15 MemAllocSeg ......................................................... 15 BGI ................................................................. 16 TMemoryStream ....................................................... 16 Heap Overrun ........................................................ 17 Program Halt ........................................................ 17 WINCRT .............................................................. 17 Page 3 INTRODUCTION____________________________________________________________ ___ Why Heap Debugging ? _______________________________________________ The Heap Debugger controls (nearly) all by the program preformed heap operations and writes among other things a list of all heap memory areas that were not released. The programmer, who uses the Heap Debug- ger while developing his program, will be notified about the remaining Memoryblocks after every ending of his program. The Heap Debugger makes the finding of mistakes extremely easy, because it gives (often) a note about the source code location (file name and line number), where incorrect heap operations were preformed, or where a not released memory block was allocated. Herefor the Heap Debugger uses the debug information for the external Debugger, that (optionally) the is created by the compiler and that extends the EXE-files. ___ What the Heap Debugger CAN do ______________________________________ The Heap Debugger controls all allocations of meap memory, that are performed with the commands - GetMem - New - FreeMem - Dispose Also calls of these routines from within the runtime-library and from program-parts, that are not available in sourcecode (for example foreign TPU's) are considered. All non correct deallocated heap memory blocks and other false heap operations are listed in the Heap Debugger Report. ___ What the Heap Debugger CANNOT do ___________________________________ The following heap operations cannot be controlled by the Heap Debugger: - Mark and Release (are not allowed to be used !) - direct access to the global heap (DPMI+Windows), so all "Global..."-calls - direct access to the local heap (Windows), so all "Local..."-calls ___ The Usage of Dynamic Memory _______________________________________ In programs, that uses heap memory intensively, not seldom treacherous programming errors are made: when dynamicly requested memory blocks are not released correctly, the available heap memory stepwise shrinks all together, so that sometime for a new request not enough space remains and the program may stop or collapse. Page 4 It only comes to a complete consumption of the heap memory, when allocations without deallocating, not only once, but again and again are preformed. Such allocations could work a few hundret times until the whole heap memory is used up. So such crashes will normally happen later to the user, who of course does not know why. There are also allocations, that only once, so for instance in the initialg process are done, because the program uses heap memory space for quasi-static variables. The programmer could allocate such variables (respectively structures or objects) into the data segment (as global variables), but since the size of the data segment is limited to a total of 64KB, he will sometimes misuse the Heap as a way out. When such (only once allocated) quasi-static variables are not released, then this is only a disfigurement, and has no other consequences. The Heap Debugger criticizes of course also such offences. Particularly treacherous are deallocation errors, that means incorrect released memory. A deallocation error is when with the releasing of heap memory a false address or a false length is directed, so to the undertaken deallocation no allocation was processed before. Since the runtime-library mostly relies upon the information the programmer gives, deallocation errors can have disastrous consequences. Especially the object oriented programming makes intensively use of heap memory. For every new dynamic instance of an object type there will be a heap allocated for the fields of the object, that when deleting then object instance must be released. Herefor you use the commands NEW and DISPOSE in the for OOP-use extended syntax. Also forgotten objects consume heap memory. ___ Versions and Targetplatforms _______________________________________ The Heap Debugger was developed and tested with Borland Pascal V7.0 and V7.01 with the target systems - Real Mode (for this HDEB7?.TPU) - Protected Mode (for this HDEB7?.TPP) - Windows (for this HDEB7?.TPW) under - DOS 6.2x - Windows V3.1 - Windows for Workgroups V3.11 - Windows NT 3.5 Workstation - OS/2 V2.11. A Version for Delphi V1.0 for Windows is be prepared. Page 5 ___ List of the Files __________________________________________________ USEHDEB.PAS .... Unit to link to your pascal program, for DOS, DOS/DPMI and WINDOWS HDEB7S.TPU ..... The core of the Heap Debugger, shareware version, for DOS/Real Mode HDEB7S.TPP ..... The core of the Heap Debugger, shareware version, for DOS/Protected Mode HDEB7S.TPW ..... The core of the Heap Debugger, shareware version, for Windows HDEB7F.TPU ..... The core of the Heap Debugger, registered version, for DOS/Real Mode HDEB7F.TPP ..... The core of the Heap Debugger, registered version, for DOS/Protected Mode HDEB7F.TPW ..... The core of the Heap Debugger, registered version, for Windows VIEWME.EXE ..... The Heap Debugger in pictures (sliteshow, req. VGA) README.TXT ..... This text (english) LIESMICH.TXT ... This text (german, in mare correct grammer!) DIZFILES.ZIP ... Short description-files, for Sysops SHARWARE.ZIP ... This file only conmes with registered versions and contains the sharewareversion BESTELL.TXT .... Orderform (german) ORDER.TXT ...... Orderform (english) ___ Shareware Concept __________________________________________________ The Heap Debugger is Shareware, not Public Domain or Freeware! The through the shareware distributers delivered version of the Heap Debugger with the files HDEB7S.* ("S"=Shareware) and the accompanied files and the file USEHDEB.PAS are allowed to be used for test purposes and are allowed to be distributed freely. The shareware version is towards the registered version in its capacity limited: The shareware version of the Heap Debugger controls only the first 50 allocations of memory blocks. All following allocations will be ignored. When exceeding the shareware limit there will come an appropriate message in the report (at the end of the program). Registered versions of the Heap Debuggers contain the files HDEB7F.* ("F"=Full). These files are not allowed to be distributed to third, or to be made available for them. ___ Licence Conditions _________________________________________________ If you want to use the Heap Debugger in the unlimited version, you have to register. With the delivery of the software you will receive a licence for the usage on a single workstation. If you want to use the Heap Debugger on several workstations then you have to register for every Workstation. Herefor we offer cheaper prices. A registration form is in the file ORDER.TXT prepared. Distribution of the registered version of the Heap Debugger is absolutely prohibited. Especially the files HDEB7F.* must not be delivered to thirds. Page 6 ___ Usertips and Warranty Limitations __________________________________ Although we tested the Heap Debugger in detail before publishing, we cannot give a guarantee for error-free function of this software. We suggest the usage of the Heap Debugger only during the developing phase. The Heap Debugger shall help you in your software development to avoid errors with the memory managment or delete them. We point to the additional dangers of the stability of a software, that involves the Heap Debugger. More information is given in the section "Stability and Performance". For registered versions of the Heap Debugger we warrant the physical media to be readable. We specifically disclaim all other warranties! Using the Heap Debugger ________________________________________________ ___ Linking the Heap Debugger __________________________________________ To link the Heap Debugger into your program, you only have to insert the unit UseHDeb in the uses-clause of your main program. For Example: PROGRAM MyProg; UseHDeb, \ / \/ USES Drivers, Objects, Views, Menus, ... It is a good idea, to list the Unit UseHDeb as the first Unit in the uses-clause. The initialization of the Heap Debugger is done by the initialization-section of this Unit. After the initialization the Heap Debugger can "watch" heap operations. That is why the initialization of UseHDeb should be done before other Units, that possibly already preform heap operations. ___ Compiler- and Linkeradjustments __________________________________ "D+": The Heap Debugger will only be initialized when the Unit UseHDeb is compiled with the option "D+" (debug-informations on). This is caused by, that almost the whole Unit UseHDeb is excepted from the compilation with the clause {$IFOPT D+}...{$ENDIF} otherwise. So this switch can be used to turn the Heap Debugger on and off, alltho theoretic the Heap Debugger could work without the D+ being turned on. All other Units, that are integrated in your program and also the main program need to be compiled with the option D+ turned on, if you want the to get source code references within the report. Page 7 "Link-Buffer: Disk" and "Standalone Debugging": Beside the compiler option D+ the adjustments "Link-Buffer: Disk" and "Standalone Debugger" are also required. Under Windows the last option is called "Debug-Info in EXE". "Unit-Directories: \BP\RTL\WIN" (DOS/DPMI and Windows): The Unit UseHDeb needs in the protected mode (DOS+Windows) the Unit WINPROCS. This is found normally in the directory "\BP\RTL\WIN". Since under DOS this index is normally not adjusted as a Unit-Directory (see Options-->Directories), you must add this directory to the list of unit-directories yourself. ___ When the Initialization fails ______________________________________ The initialization of the Heap Debugger is done through the initiali- zation section of the unit UseHDeb. When it fails the UseHDeb reports "Unable to initialize the Heap Debugger !" and stops the program with the command HALT. The failing of the Initialization can have following reasons: - You are using a modified runtime-library, that in a for the Heap Debugger important point does not match with the original from Borland. - You are using an operating system or a special tool (e.g. memory management tool) that wasn't verified to supported. - You are using an unsupported compiler version. - There were no free interrupt vectors found. The Heap Debugger needs three free interrupts. In this case probably our test method for finding free interrupts did fail. It is extremely rare that all interrupts are really used. - The Heap Debugger is already initialized. This should not happen when you use the Unit UseHDeb. When in your system the initialization fails, then please try to run your program within a tested configuration (for instance: MSDOS 6.2 , Windows 3.1) without loading any special memory managers or multi- taskers. Observe if the Heap Debugger can now be initialized in this configuration. Please inform us about configuration in, with that the Heap Debugger could not be used. (if possible per email) ___ The Heap Debugger Report ___________________________________________ The Heap Debugger gives a report when ending a program. This happens in the exit-procedure of the unit UseHDeb. The Heap Debugger Report has normally the following structure (for example:) Page 8 HEAP DEBUGGER DIAGNOSIS: 2 pointer were registered (*1) 1 debug-entries available (*2) list (Y/N) ? y (*3) (*4) (*5) (*6) (*7) |------(*8)------| No Pointer Size Flags Caller File Line 2 1A41:0000 256 0000[122D]:0044 HEAPBUG.PAS 16 (*1): Here is printed, how many heap allocations the Heap Debugger did observe in total. This number means no statement about possible mistakes. (*2): Here is printed, how many diagnosis lines the Heap Debugger has available to dump. In the best case this number should always be "0". Not all but most of the diagnosis lines point towards a programming error. (*3): Here is a sequential counter of all in the program done allocations. With deallocations (Flag "F") this place is empty. (*4): Here is the addresses of the allocated respectively deallocated heap memory block printed. This address can vary from program-run to program-run. (*5): Here is the size of the allocated respectively deallocated block printed. (*6): The here listed Flags have following meanings (combinations are possible): none : Its about an allocation, to that no fitting deallocation was performed. "O" : Its about an instance-data of an object type. This is the data area, that is created by the constructor of a object with every new instance. As caller is the line with the word "BEGIN" in the costructor given (the line with the word "END" in the destructor at deallocations). "F" : This diagnosis line deals with a deallocation (F=free). What went wrong with this deallocation is explained in one of the following flags. "S" : A heap memory block was not in the same blocklength (S=size) deallocated, with which it was allocated. In this case, the flag will appear both in the diagnosis lines of the allocation and of the deallocation. "M" : To a deallocation there was not a fitting allocation found (M=mismatch). This means, it was tried, to deallocate a heap memory block, who's address was not registered by a previous allocation. This flag appears only together with the flag "F". (*7): At this address the heap operation, that this diagnosis line is about, was called. The segment address is the virtual segment address and in brackets "[]" the actual segment address. The virtual segment address is generated by the linker and is the address relative to the address 0000. The actual segment address will be given when loading a program and depends on the location, at which the program is loaded into memory. The virtual address can be found in the map-file. The actual address can vary from program-run to program-run. Page 9 (*8): Here the sourcecode location (file name and line number) ist shown according to the caller address. It is required that the debug information exist in the EXE-file. If there are no debug informations present "No Info" will be printed here. If there are debug informations present but the sourcecode-line of the caller address couldn't be found nonetheless, a "?" will be printed here. ___ Special Messages in the Heap Debugger Report _______________________ The following messages can appear under special circumstances: "Program stopped by HALT(nnn)" This message says, that the program was stopped with the command HALT(nnn). The Exitcode is given with nnn. "runtime-error nnn at ssss:oooo, file: ________ line: ______" When the program is stopped through a runtime error, this message will be present. As additional, useful information the file name and line number of the error are printed, if this information is available. "internal error 203 occured in Heap Debugger" This message means, that the Heap Debugger did not have enough heap memory to record all heap operations. "Shareware-limit exceeded! Only 50 pointers were registered!" This message will only be printed in the shareware version and tells us that the shareware limit of 50 controlled allocations was exceeded during the runtime. ___ Interpretation of the Report _______________________________________ Of course you should attempt to receive the message "0 debug-entries available", at the end of a program-run. If the Heap Debugger is continually in action during the development of a application, then an possibly reported bugs can easly be found, because the error most often was made during the last changes to the program. If the matter isn't so easy, then you first need to understand the diagnosis of the Heap Debugger, to solve the problem. For this purpose you need to ask yourself following questions: - Is the number of the diagnosis entries always the same, or does this number vary? As far as the number does not vary, then it must have to do with an error that happens only once a program-run. There are cases, in that the name error is to strong. Some programs allocate some quasi-static variables on the Heap, and don't release them at the end. This behavior is not very nice and should be tried to be avoided; on the other hand this has no bad consequences. Page 10 - Can the increase of the number of diagnosis lines have to do with certain functions of my program? If the number grows, then you should try to find the obviously repeated error. Most often this is very easy, when the Heap Debugger gives for several entries the same caller address. It then appears to be a error, that always occurs when a certain program function is executed. You should always get rid of these errors, because they can cause "loss of memory". - Are there any Flags in a diagnosis lines? If not, then this diagnosis denunciats a "classic" error, particulary a not released "normal" heap memory block, that was allocated with GetMem or New. The sourcecode reference refers to the location, were this demand happened. - Is the Flag "O" present ? If yes, the Heap Debugger shows an error in relation to an object. If there is just an "O" entered, then this has to with a not released dynamic instance of an object, which was set up with the command new in the OOP-variation. The sourcecode reference does NOT point to this New-command, but to the line BEGIN in the concerned constructor. If you found out this, you need to think about where the instances of this object type is allocated and to and check for the correct releasement. - Is th Flag "F" present ? This flag appears never alone. It means (mostly), that a deallocation error has occurred. Beside the "F" there will always be a "S" or a "M", which means, that either a deallocation with a false block length was called, or that the deallocated memory block has an address, where no allocation was done. This diagnosis is either real bad or harmless. The harmless case is described in the section "MemAllocSeg". If this description doesn't prove, then there is probably a REAL error, that has to be found, because it could cause the whole program (also the Heap Debugger) to crash. This can happen, if the consistency of the heap management becomes damaged. ___ Hunting for Bugs ___________________________________________________ If the Heap Debugger gives with his diagnosis sourcecode references, then is the finding of bugs relatively easy. If instead of a sourcecode reference a "?" is printed, then the under "Caller" listed address is in an module, that has not debug informations because is wasn't compiled with the option "D+". Often you can find the caller in the runtime-library. You should not let yourself come to the conclusion, that you are not responsible for the error and that the runtime-library has a Bug. If you for instance do an allocation with "NewStr" (function of the runtime Page 11 library) and the requested heap memory block then is not deallocated afterwards with DisposeStr, then the error is in your program. But the caller is a line in the function NewStr in the runtime library. A lot of these problems can be solved, if you recompile the whole run- time-library with the debug-option. This is only possible with BP7.0 (not with TP7.0). Informations for this you find in Borland's \BP\RTL\README. ___ Working with the External Debugger _________________________________ In hard cases you should try to find an error with the help of the external debugger. That makes sense when the Heap Debugger did not give sourcecode references. In the external Debugger you should set a breakpoint at the callers address. Please notice the difference between the virtual and the actual segment address, that the Heap Debugger prints. Attention: The actual segment address of the caller can vary from program-run to program-run. After loading the Debugger it will mostly move. Let your program run once or a few times with the loaded debugger before you set a breakpoint. Use the last given actual segment address. You can set a breakpoint at any adress function "Breakpoints-At...". Just enter the caller address and start the segment address AND the offsetaddress with a "$" for hexadecimal notation. When you reach a breakpoint, continue the execution stepwise until you reach an area that you know. ___ Compilerswitches in USEHDEB ________________________________________ In the Unit UseHDeb there are already a few compiler switches established, that eases the adjustment. We hope, that the most adjustment problems can be solved, so that you don't need to change the source code. The Switch "USE_SHAREWARE": When this switch is defined, the Heap Debugger uses the unit "HDEB7S.TP?". When it is undefined, then the Units "HDEB7F.TP?" is integrated. This stands for the registered version of the Heap Debugger and can of course only be used, if the software was registered. This switch is correctly adjusted in the delivered shareware or the registered version and does normally not need to be changed. The Switch "GERMAN_LANG": When this switch is defined, the Heap Debugger Report will be given in german language instead of english. Page 12 The Switch "GETDEBUGINFO": When this switch is defined, then the Heap Debugger will try to access to the debug informations in the EXE-file to find out the file name and line number for every diagnosis line. This switch should normally stay active. The Switch "REPORT_TO_FILE": When this switch is defined, then the report output will be transferred into a file. The name of this file in defined in the constant "DumpFileName" and that is preadjusted to "HEAPDEB.DMP" but can be changed. The file will be enlarged with every report output. Please note: When the Heap Debugger because of any reason cannot be initialized and the switch "REPORT_TO_FILE" is active, then the program will be stopped with the command "HALT" without any warning (also in the file). The Switch "SWITCH_TO_LASTMODE": When this switch is defined, the command "TextMode(LastMode)" will be executed before the report output starts. The command switches back into the videomode, that was active at the start of the program. This can be very helpful when the main program switches to a graphics mode that isn't BIOS-supported or when textcolors are modified in a way, that the report in not readable. This switch does nothing under Windows. Example for turning switches off and on: active: "{$DEFINE GERMAN_LANG}" inactive: "{not $DEFINE GERMAN_LANG}" HEAP DEBUGGING IN DETAIL _______________________________________________ ___ Overlays ___________________________________________________________ You can use the Heap Debugger also with programs, that uses overlay- technics. The Units USEHDEB and HDEB7? cannot be loaded as overlays. ___ DLLs _______________________________________________________________ A DLL can be treated just like a normal self-running program. If a program, that is using the Heap Debugger, loads a DLL at runtime, then the Heap Debugger is not active for this DLL. On the other hand a DLL can use the Heap Debugger, without the heap operations in the main program being controlled. If the Heap Debugger is used for the DLL and the main program, then there will be two reports printed. To link the Heap Debugger to a DLL just insert the unit UseHDeb in the uses-clause of the librarys main file (with the title "Library"). The exit-procedure of the unit UseHDeb (with the Reportoutput) will be done when the DLL ends. When is this? The DLL normally ends, when also the main program, that loaded the DLL, ends. But there are exceptions: If the main program is run with the external debugger, then the DLL will not end when the program is ended, but when the debugger is ended, what Page 13 very often leads to a system crash. We suggest to use the command "FreeLibrary" to unload a DLL that uses the Heap Debugger. The report for the DLL will than be printed immediately. What was just described counts for DLLs under DOS and WINDOWS the same. Under Windows there is also another problem: The report output, that is done by the unit UseHDeb under Windows is printed into a WinCrt-window. That does not work with a DLL: The consequence of the try, to write into a WinCrt-window from within a DLL, is a runtime error or a complete missing of the output. Under DOS this problem will not occur. When using the Heap Debugger under Windows for a DLL, it is absolutely necessary to dump the report into a file. Herefor the switch "REPORT-TO-FILE" was prepared (see "Compilerswitches in USEHDEB"). ___ Program Instances (Windows) ________________________________________ When under windows a program, that links the Heap Debugger is started in several instances, the Heap Debugger will be installed only for the first instance. The following instances automatically use the already installed Heap Debugger. The output of the report will not be done until the ending of the last active instance of that program. The report then contains all wrong heap operations, that were done in all instances of that program. ___ Interrupts ________________________________________________________ The Heap Debugger needs three free software interrupts. This means that when the Heap Debugger is installed it changes three free interrupt vectors and releases them at the end of the program. The Heap Debugger finds the free vectors itself within the range 78h to FFh. From this range you can exclude single vectors if you need some special vectors for own purposes. To do so you must change the parameter of the command "HeapDebInit([])". Change the empty set to set of vectors that you want be be left unchanged, e.g. "HeapDebInit([$F0..$FF]). ___ Stability and Performance __________________________________________ As already explained the Heap Debugger should not be used as a part of a finished application. The Heap Debugger should only be used during the developing phase as a debugging tool. The permanent use of the Heap Debugger during the software development can help stabilize the developed software a lot and shorten the developmenting time. On the other hand the Heap Debugger can be a potential cause for program crashes, even if this has not been discovered yet. Following facts should be watched: - The Heap Debugger not only controls the correct usage of the heap memory. It also requires meap memory itself for this task. If a program occasionally has to allocate a large number of heap memory blocks, so the amount of needed extra memory for the Heap Debugger can be high. You should count with an extra 24 bytes for each allocated (and not yet deallocated) memory block. Page 14 - The execution of the Heap Debugger requires extra space on the stack, as well as the execution of the memory operations and also the output of the report in the exit-procedure of the unit UseHDeb. Please notice that no stack-checks are done so that a lack of stack-space will cause a program crash. - When fatal errors in the application program are made in using the meap that can bring the program to a collapse. There might be constallations, in that the program doesn't crash when the Heap Debugger isn't linked. Nevertheless the causing error is dangerous. Such crashes can for instance happen, when the application tries to release a not allocated memory block. - The Heap Debugger needs for its work additional CPU-time. The more memory blocks are allocated, the more CPU-time the Heap Debugger requires, especially for releasing memory. - The Heap Debugger requires, as in the previous section mentioned, for its work three free software interrupts. The tree vectors are set to the addresses of three functions within the Heap Debugger and restored at the end of the program. When a program suddenly ends because of a fatal error and the exit procedure of the Unit UseHDeb insn't executed, then the interrupt vectors are not set to their old values. If such crashes happen very often, the Heap Debugger might not be able to find any free Interrupts and wont start. ___Intervention possibilities for the Programmer _______________________ If you perhaps like to change the appearance of the Heap Debugger Report you can modify the sourcecode of the unit UseHDeb. Changes are only allowed for your own, non-commercial use. Beside the unit UseHDeb offers the following constants, which can be changed during at runtime: 1) SuspendHeapdeb : Boolean = false; If this constant is set to TRUE at runtime, then there will be no heap operations recorded by the Heap Debugger. After the reconversion of the value to FALSE the Heap Debugger will work normal. This can be useful to prevent quasi-static variables being listed in the report. 2) RecordZeroSize : Boolean = false; As long as this constant is FALSE, allocations and deallocations with the a length of zero be ignored by the Heap Debugger. Because such operations are just disfigurements and (as far as we know) cant make damage, this constant is preadjusted to FALSE. 3) RTEOnWrongSizedFree : Byte = 0; If in this constant is not zero, every deallocation, that doesn't have the same length as the fitting allocation (Flag "S"), will cause a runtime error immediately. The number of the runtime error is determined by this constant. 4) RTEOnUnknownFree : Byte = 0; If in this constant is not zero, every deallocation with not matching allocation (Flag "M"), will cause a runtime error immediately. The number of the runtime error is determined by this constant. Page 15 KNOWN LIMITATIONS AND PROBLEMS _________________________________________ ___ Mark/Release _______________________________________________________ The Heap Debugger doesn't work with these commands. The usage of Release can cause the records of the Heap Debugger being destructed. However the commands Mark and Release are seldomly used, because they bring other problem with them in general. Probably they are still in the newest version of the compiler because of the compatibility. The usage of Mark and Release we generally do not advise. Mark and Release are only available under DOS. ___ MemAllocSeg ________________________________________________________ The function MemAllocSeg in the unit Memory (under Windows: OMemory) is a big problem for the Heap Debugger: The job of this function is, to allocate a heap memory area, who's start address is exactly at the start of a memory segment (at the offset address 0000). To reach this, the function MemAllocSeg must use some tricks. We have to make differences between the target-platforms: Real Mode: To allocate a heap memory area with the offset address 0000, the function MemAllocSeg reserves with GetMem initially a little larger area, to afterwards immediately release with FreeMem a small part (8 Bytes), that is either located at the start or at the end of the just allocated area. Altho this is an offence against the rules, this trick isnīt really illegal. The Heap Debugger "watches" these operations and will later list them in its report. This can for instance look like this: program TEST; uses UseHDeb, Memory; var p: pointer; begin {...} p := MemAllocSeg(100); FreeMem(p, 100); end. HEAP-DEBUGGER-DIAGNOSIS: 1 pointers were registered 3 debug-entries available list (Y/N) ? y No Pointer Size Flags Caller File Line 1 1A4D:0000 112 S 020B[1438]:001F MEMORY.PAS 327 1A53:0008 8 F M 020B[1438]:00D5 MEMORY.PAS 355 1A4D:0000 100 FS 0000[122D]:003A TEST.PAS 7 Or so: Page 16 HEAP-DEBUGGER-DIAGNOSIS: 1 pointers were registered 3 debug-entries available list (Y/N) ? y No Pointer Size Flags Caller File Line 1 1531:0008 112 S 020C[0F1A]:001F MEMORY.PAS 327 1531:0008 8 FS 020C[0F1A]:00D5 MEMORY.PAS 355 1532:0000 100 F M 0000[0D0E]:004A TEST.PAS 7 The programmer is more or less being forced, to accept such operations altho they appear risky. Protected Mode (DOS/DPMI): Here the function MemAllocSeg has it easier then in Real Mode: It just calls the function "MemAllocateBlock", which is made available by RTM.EXE that calls a corresponding DPMI-function. Through this a heap memory block is allocated, that starts at the offset address 0000. As already explained in section "Global and Local Heap", the Heap Debugger notices nothing of this. The releasing of this heap memory block is normally done with the function FreeMem, about what the Heap Debugger takes notice. Our test program would show in the protected mode the following report: HEAP-DEBUGGER-DIAGNOSIS: 0 pointers were registered 1 debug-entries available list (Y/N) ? y No Pointer Size Flags Caller File Line 059F:0000 100 F M 0001[0547]:003D TEST.PAS 7 Windows: Here we have the same situation as in the protected mode under DOS, except that the MemAllocSeg uses the function "GlobalAlloc" to allocate heap memory at the offset address 0000. Since this is a Global Heap- operation, the Heap Debugger will not notice anything. The releasing of this heap memory area with FreeMem will be registered. The consequence for the Heap Debugger is the same as in the protected mode. ___ BGI ________________________________________________________________ During the initializing of BGI-Drivers the same phenomenon as described in the section "MemAllocSeg" might occur. Mostlikely the BGI-Drivers or the unit Graph have their own implementation of the function "MemAllocSeg". ___ TMemoryStream ______________________________________________________ The method "ChangeListSize" of this stream-object uses MemAllocSeg, which was described above. Page 17 ___ Heap Overrun _______________________________________________________ The Heap Debugger, that is supposed to control the heap operations of a program, also needs heap memory for its work. In case the heap debugger cannot request anymore heap memory, because this is used up, then there will be an internal error number 203 reported. When the main program defines a heaperror-function, then this will be executed when a heap allocation in the Heap Debugger fails. ___ Program Break ______________________________________________________ When a program, that uses the Heap Debugger, breaks execution without the exit-procedure of the unit UseHDeb is being run, then the by the Heap Debugger changed software interrupt vectors will not be restored. Non restored interrupt vectors, that are not used elsewhere, are of no danger. During a new Initialization of the Heap Debugger by a repeated run, there will be three other interrupt vectores searched. If the "hard" breaks repeat (approx. 40 times), there will sometime be no more free interrupt vectores and the Heap Debuggerīs initialization will fail. This then can only be fixed by a reboot of the computer. ___ WINCRT _____________________________________________________________ If the main program is already using a WinCrt-Window and this is not closed with DoneWinCrt, before the exit-procedure of the Unit UseHDeb is run, then typically 2000 bytes of heap memory stay allocated, that then is listed in the Heap Debugger Report. Anyhow you should not be program a DoneWinCrt-command into the main program, because this brings up new problems. As already described in the section "DLLs", the Heap Debugger cannot dump into a WinCrt-window when a DLL is being used. In case of doubt you should try to take advantage of the possibility of the dumping the report into a file.